import React, { memo, useState, useEffect, useRef, useCallback } from "react";
import { useDispatch, useSelector, shallowEqual } from "react-redux";
import { NavLink } from "react-router-dom";

import {
  getSizeImage,
  formatMinuteSecond,
  getPlayMusic,
} from "@/utils/format-utils";
import {
  getSongDetailAction,
  changeSequenceAction,
  changeCurrentIndexAndSongAction,
  changeCurrentLyricIndexAction,
} from "../store/actionCreators";

import { Slider, message } from "antd";
import HYAppPlayerPanel from "../app-player-panel";
import { PlayerWrapper, Control, PlayInfo, Operator } from "./style";

export default memo(function HYAppPlayerBar() {
  const [currentTime, setCurrentTime] = useState(0);
  const [progress, setProgress] = useState(0);
  // 当前 progress 是否正在改变
  // 因为正常 progress 和手指滑动改变 progress 会有冲突
  const [isChanging, setIsChanging] = useState(false);
  // 播放按钮点击，播放音乐，再点击一次，停止播放
  const [isPlaying, setIsPlaying] = useState(false);
  const [showPanel, setShowPanel] = useState(false);

  const { currentSong, sequence, lyricList, currentLyricIndex, playList } =
    useSelector(
      (state) => ({
        currentSong: state.getIn(["player", "currentSong"]),
        sequence: state.getIn(["player", "sequence"]),
        lyricList: state.getIn(["player", "lyricList"]),
        currentLyricIndex: state.getIn(["player", "currentLyricIndex"]),
        playList: state.getIn(["player", "playList"]),
      }),
      shallowEqual
    );

  const dispatch = useDispatch();
  const audioRef = useRef();

  useEffect(() => {
    dispatch(getSongDetailAction(167876));
  }, [dispatch]);

  // 因为每次都根据 currentSong 的 id 来更新音乐
  useEffect(() => {
    audioRef.current.src = getPlayMusic(currentSong.id);
    audioRef.current
      .play()
      .then((res) => {
        setIsPlaying(true);
      })
      .catch((err) => {
        setIsPlaying(false);
      });
  }, [currentSong]);

  const picUrl = (currentSong.al && currentSong.al.picUrl) || "";
  const singerName = currentSong.ar && currentSong.ar[0].name;
  // 单位是 ms
  const duration = currentSong.dt || 0;
  console.log(duration);
  const showDuration = formatMinuteSecond(duration);
  const showCurrentTime = formatMinuteSecond(currentTime);
  // 歌曲进度
  // const progress = currentTime / duration * 100;

  // 点击播放按钮开始播放音乐
  // 性能提升：useCallback 因为每次组件渲染的时候，由于 playMusic 是局部变量，每次都会
  // 重新创建，所以 sliderAfterChange 每次也会发生变化，就没有起到性能提升的作用
  const playMusic = useCallback(() => {
    console.log(isPlaying);
    // 手动调用播放按钮
    isPlaying
      ? audioRef.current.pause()
      : audioRef.current.play().catch((err) => {
          setIsPlaying(false);
        });
    setIsPlaying(!isPlaying);
  }, [isPlaying]);

  // 点击上一首还是下一首来播放歌曲
  const changeMusic = (tag) => {
    dispatch(changeCurrentIndexAndSongAction(tag));
  };

  // 顺序播放，单曲循环，随机播放
  const changeSequence = () => {
    let currentSequence = sequence + 1;
    if (currentSequence > 2) {
      currentSequence = 0;
    }
    dispatch(changeSequenceAction(currentSequence));
  };

  // 监听歌曲进度实时改变歌曲的时间
  const timeUpdate = (e) => {
    const currentTime = e.target.currentTime;
    // 手指在滑动过程中依然是之前的播放音乐
    if (!isChanging) {
      setCurrentTime(currentTime * 1000);
      // 一般情况下 progress
      setProgress(((currentTime * 1000) / duration) * 100);
    }

    if (currentTime) {
      // 显示歌词的处理
      // 可以有一些性能优化
      let index = 0;
      for (let i = 0; i < lyricList.length; i++) {
        let lyricItem = lyricList[i];
        if (lyricItem.time > currentTime * 1000) {
          index = i - 1;
          break;
        }
      }
      if (currentLyricIndex !== index) {
        dispatch(changeCurrentLyricIndexAction(index));
        const content = lyricList[index] && lyricList[index].content;
        message.open({
          // 当 key 相同的时候，它只会出现一个
          key: "lyric",
          content: content === "" ? "歌词面板" : content,
          duration: 0,
          className: "lyric-class",
        });
      }
    }
  };

  // 一首音乐播放完毕
  const handleMusicEnded = () => {
    if (sequence === 2 || playList.length === 1) {
      // 单曲循环
      audioRef.current.currentTime = 0;
      audioRef.current.play();
    } else {
      dispatch(changeCurrentIndexAndSongAction(1));
    }
  };

  // useCallback 什么时候使用，当你把一个函数传入自定义组件内部的时候，slideChange 重绘的时候，
  // 组件也会跟着重绘，非常影响性能，所以出现了 useCallback
  const sliderChange = useCallback(
    (value) => {
      setIsChanging(true);
      // 手指在滑动过程中时间会发生改变
      const currentTime = (value / 100) * duration;
      setCurrentTime(currentTime);

      // 手指滑动过程中改变 progress
      setProgress(value);
    },
    [duration]
  );

  const sliderAfterChange = useCallback(
    (value) => {
      const currentTime = ((value / 100) * duration) / 1000;
      audioRef.current.currentTime = currentTime;
      // 这句代码主要是为了解决回退问题
      setCurrentTime(currentTime * 1000);
      setIsChanging(false);

      if (!isPlaying) {
        playMusic();
      }
    },
    [duration, isPlaying, playMusic]
  );

  // window.onload = () => {
  //   setIsPlaying(false);
  //   audioRef.current.pause();
  // };
  return (
    <PlayerWrapper className="sprite_player">
      <div className="content wrap-v2">
        <Control isPlaying={isPlaying}>
          <button
            className="prev sprite_player"
            onClick={(e) => changeMusic(-1)}
          ></button>
          <button
            className="play sprite_player"
            onClick={(e) => playMusic()}
          ></button>
          <button
            className="next sprite_player"
            onClick={(e) => changeMusic(1)}
          ></button>
        </Control>
        <PlayInfo>
          <div className="image">
            <NavLink to="/discover/player">
              <img src={getSizeImage(picUrl, 35)} alt="" />
            </NavLink>
          </div>
          <div className="info">
            <div className="song">
              <span className="song-name">{currentSong.name}</span>
              <a href="#/" className="singer-name">
                {singerName}
              </a>
            </div>

            <div className="progress">
              <Slider
                defaultValue={30}
                value={progress}
                onChange={sliderChange}
                onAfterChange={sliderAfterChange}
              />
              <div className="time">
                <span className="now-time">{showCurrentTime}</span>
                <span className="divider">/</span>
                <span className="duration">{showDuration}</span>
              </div>
            </div>
          </div>
        </PlayInfo>
        <Operator sequence={sequence}>
          <div className="left">
            <button className="sprite_player btn favor"></button>
            <button className="sprite_player btn share"></button>
          </div>
          <div className="right">
            <button className="sprite_player btn volume"></button>
            <button
              className="sprite_player btn loop"
              onClick={(e) => changeSequence()}
            ></button>
            <button
              className="sprite_player btn playlist"
              onClick={(e) => setShowPanel(!showPanel)}
            >
              {playList.length}
            </button>
          </div>
        </Operator>
      </div>
      <audio
        volume={0.01}
        ref={audioRef}
        onTimeUpdate={timeUpdate}
        onEnded={handleMusicEnded}
      />
      {showPanel && <HYAppPlayerPanel />}
    </PlayerWrapper>
  );
});
